package titt.server.service;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import titt.io.socket.TITTSocket;
import titt.key.TITTKey;
import titt.server.service.listener.ServiceListener;
import titt.service.ServicePackage;

public class LinkedService implements Service {
	
	private final Service s;
	private final TITTKey key;
	private final String id;
	private final String[][] iface;
	
	private Set<String> packs = new HashSet<String>();
	private ArrayList<ServiceListener> listeners = new ArrayList<ServiceListener>();
	private boolean stopped;
	
	public LinkedService(TITTKey key, String id, String[][] iface, Service s) {
		this.key = key;
		this.id = id;
		this.iface = iface;
		this.s = s;
	}

	@Override
	public void addDependency(TITTSocket ts) throws Exception {
		s.addDependency(ts);
	}

	@Override
	public synchronized void attachServiceListener(ServiceListener sl) {
		if(stopped)
			sl.onServiceStop();

		listeners.add(sl);
		s.attachServiceListener(sl);
	}

	@Override
	public void deposit(ServicePackage pack) {
		synchronized (this) {			
			packs.add(pack.getPackageID());
		}
		s.deposit(pack);
	}

	@Override
	public String getID() {
		return id;
	}

	@Override
	public TITTKey getKey() {
		return key;
	}

	@Override
	public String[][] getRegistrationInterface() {
		return iface;
	}

	@Override
	public long lastSuccess() {
		return s.lastSuccess();
	}

	@Override
	public void removeDependency(TITTSocket ts) throws Exception {
		s.removeDependency(ts);
	}

	@Override
	public synchronized void removeServiceListener(ServiceListener sl) {
		listeners.remove(sl);
		s.removeServiceListener(sl);
	}

	@Override
	public void stop() throws Exception {
		synchronized (this) {
			stopped = true;
			
			for(ServiceListener sl : listeners)
				sl.onServiceStop();
			
			packs.clear();
			notifyAll();
		}
	}

	@Override
	public synchronized void waitForCompletion(int maxSec) throws Exception {
		long max = System.currentTimeMillis() + maxSec * 1000;
		while(packs.size() > 0 && System.currentTimeMillis() < max)
			wait(Math.max(1,max - System.currentTimeMillis()));
	}
	
	@Override
	public void sync(ServicePackage pack) {
		s.sync(pack);
		synchronized (this) {
			packs.remove(pack.getPackageID());
			notifyAll();
		}
	}
	
	@Override
	public ServicePackage withdraw() throws Exception {
		return s.withdraw();
	}

	@Override
	public int compareTo(Service o) {
		return key.compareTo(o.getKey());
	}
	

}
